{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "honest-exhibition",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\qq455\\anaconda3\\envs\\nlp\\lib\\site-packages\\numpy\\_distributor_init.py:32: UserWarning: loaded more than 1 DLL from .libs:\n",
      "C:\\Users\\qq455\\anaconda3\\envs\\nlp\\lib\\site-packages\\numpy\\.libs\\libopenblas.TXA6YQSD3GCQQC22GEQ54J2UDCXDXHWN.gfortran-win_amd64.dll\n",
      "C:\\Users\\qq455\\anaconda3\\envs\\nlp\\lib\\site-packages\\numpy\\.libs\\libopenblas.WCDJNK7YVMPZQ2ME2ZZHJJRJ3JIKNDB7.gfortran-win_amd64.dll\n",
      "  stacklevel=1)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(array([[0.   , 0.   , 0.   , 0.   , 0.   , 0.   , 0.697, 0.46 ],\n",
       "        [1.   , 0.   , 1.   , 0.   , 0.   , 0.   , 0.774, 0.376],\n",
       "        [1.   , 0.   , 0.   , 0.   , 0.   , 0.   , 0.634, 0.264],\n",
       "        [0.   , 1.   , 0.   , 0.   , 1.   , 1.   , 0.403, 0.237],\n",
       "        [1.   , 1.   , 0.   , 1.   , 1.   , 1.   , 0.481, 0.149],\n",
       "        [0.   , 2.   , 2.   , 0.   , 2.   , 1.   , 0.243, 0.267],\n",
       "        [2.   , 1.   , 1.   , 1.   , 0.   , 0.   , 0.657, 0.198],\n",
       "        [1.   , 1.   , 0.   , 0.   , 1.   , 1.   , 0.36 , 0.37 ],\n",
       "        [2.   , 0.   , 0.   , 2.   , 2.   , 0.   , 0.593, 0.042],\n",
       "        [0.   , 0.   , 1.   , 1.   , 1.   , 0.   , 0.719, 0.103],\n",
       "        [0.   , 0.   , 1.   , 0.   , 0.   , 0.   , 0.608, 0.318],\n",
       "        [2.   , 0.   , 0.   , 0.   , 0.   , 0.   , 0.556, 0.215],\n",
       "        [1.   , 1.   , 0.   , 0.   , 1.   , 0.   , 0.437, 0.211],\n",
       "        [1.   , 1.   , 1.   , 1.   , 1.   , 0.   , 0.666, 0.091],\n",
       "        [2.   , 2.   , 2.   , 2.   , 2.   , 0.   , 0.245, 0.057],\n",
       "        [2.   , 0.   , 0.   , 2.   , 2.   , 1.   , 0.343, 0.099],\n",
       "        [0.   , 1.   , 0.   , 1.   , 0.   , 0.   , 0.639, 0.161]]),\n",
       " array([0., 0., 0., 0., 0., 1., 1., 1., 1., 1., 0., 0., 0., 1., 1., 1., 1.]))"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "\n",
    "#加载数据\n",
    "def load_data():\n",
    "    with open('连续值数据.txt') as fr:\n",
    "        lines = fr.readlines()\n",
    "\n",
    "    x = np.empty((len(lines), 8), dtype=float)\n",
    "    y = np.empty(len(lines), dtype=float)\n",
    "\n",
    "    for i in range(len(lines)):\n",
    "        line = lines[i].strip().split(',')\n",
    "        x[i] = line[:8]\n",
    "        y[i] = line[8]\n",
    "\n",
    "    return x, y\n",
    "\n",
    "\n",
    "x, y = load_data()\n",
    "x, y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "entitled-handle",
   "metadata": {},
   "outputs": [],
   "source": [
    "N, M = x.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "portuguese-third",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.36363636363636365"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#给定y和某列值的情况下求概率,离散值\n",
    "def get_probability(col, value, _y):\n",
    "\n",
    "    #首先根据_y分割出_x\n",
    "    _x = x[y == _y]\n",
    "\n",
    "    #分子是在_x中列col=value的数量,+1是做拉普拉斯平滑\n",
    "    fenzi = (_x[:, col] == value).sum() + 1\n",
    "\n",
    "    #分母是_x的数量,加col列的取值数量做拉普拉斯平滑\n",
    "    fenmu = len(_x) + len(np.unique(_x[:, col]))\n",
    "\n",
    "    return fenzi / fenmu\n",
    "\n",
    "\n",
    "get_probability(0, 0, 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "million-syria",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.9624922010858166"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#同上,这里是求连续值\n",
    "def get_continuous_probability(col, value, _y):\n",
    "    #式子里的这部分是常量\n",
    "    sqrt_2_pi = (2 * np.pi)**0.5\n",
    "\n",
    "    #切分数据\n",
    "    _x = x[y == _y]\n",
    "\n",
    "    #求均值和方差\n",
    "    mu = _x[:, col].mean()\n",
    "    sigma = _x[:, col].std()\n",
    "\n",
    "    #计算第一部分\n",
    "    p = 1 / (sqrt_2_pi * sigma)\n",
    "\n",
    "    #计算第二部分\n",
    "    fenzi = (value - mu)**2\n",
    "    fenmu = sigma**2 * 2\n",
    "    p *= np.exp(-fenzi / fenmu)\n",
    "\n",
    "    return p\n",
    "\n",
    "\n",
    "get_continuous_probability(6, 0.697, 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "guilty-minneapolis",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def predict(_x):\n",
    "\n",
    "    #结果是两个概率,因为是对数概率,所以初始化为0\n",
    "    #如果不是对数就需要初始化为1\n",
    "    ps = np.zeros(2)\n",
    "\n",
    "    #遍历2个y\n",
    "    for _y in range(2):\n",
    "        #遍历所有列\n",
    "        for col in range(M):\n",
    "            #6和7是连续值,其他的是离散值\n",
    "            p = None\n",
    "            if col == 6 or col == 7:\n",
    "                p = get_continuous_probability(col, _x[col], _y)\n",
    "            else:\n",
    "                p = get_probability(col, _x[col], _y)\n",
    "\n",
    "            #对数概率,连乘变连加\n",
    "            ps[_y] += np.log(p)\n",
    "\n",
    "    #取概率最高的y输出\n",
    "    return ps.argmax()\n",
    "\n",
    "\n",
    "predict(x[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "piano-iraqi",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.8235294117647058"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "correct = 0\n",
    "for xi, yi in zip(x, y):\n",
    "    if predict(xi) == yi:\n",
    "        correct += 1\n",
    "correct / N"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
